HFS PathName
Volume Number: 2
Issue Number: 7
Column Tag: Modula-2 Mods
Make a Path Name for HFS
By Tom Taylor, Santa Clara, CA, MacTutor Contributing Editor
Extending Modula-2 for HFS Support
The Macintosh low-level File Manager is probably familiar to anyone who has
programmed in another language besides Modula-2 on the Mac. Until the Heirarchical
File System was released, there wasn't a tremendous amount of motivation to use the
low level parameter block routines from Modula-2. The high-level File Manager
routines implemented by MacModula-2 were usually enough to get the job done. With
the release of the Mac Plus, however, the high level calls are not enough. Therefore, I
decided to implement a library module that includes all of the low-level File Manager
calls specified in the new chapter of the File Manager.
The Low-Level File Manager
Most people are already familiar with the low-level File Manager. For those
who are not, a little introduction would be helpful. First of all, the low-level File
Manager routines exist in ROM. The high level File Manager routines described by the
File Manager Inside Macintosh chapter do not. Instead, the high level calls consist of
glue code that calls the low-level routines. Each low-level procedure takes one
parameter: a pointer to a parameter block. This parameter block, however, is used to
hold many input and output parameters. The File Manager chapter does an excellent job
of showing which fields of the parameter block are used for each call. Before using the
module presented in this article, you must read the File Manager chapter of Inside
Macintosh. In fact, it would be most helpful if you were to read the new chapter that
explains the File Manager in terms of both MFS and HFS. There are six different types
of parameter blocks. Three of the six blocks contain variant records.
A typical low-level File Manager call looks like this:
PROCEDURE PBCallName
(paramBlock: PtrToParamBlk;
async: BOOLEAN) : OsErr;
The first parameter is a pointer to one of the six different parameter blocks.
Generally, I find it easiest to declare the actual block as a variable and then pass
ADR(block) for this parameter. The second parameter, "async", specifies whether the
routine should be executed synchronously or asynchronously. It is beyond the scope of
this article to explain how to use asynchronous calls in an interpreted system like
MacModula-2. Therefore, my example program will always perform synchronous calls
by passing FALSE for this parameter.
How it all works
The definition module, PBFileManager.DEF, is very straightforward. All of the
parameter block types and procedures are defined. The implementation module is a bit
trickier. Basically, every procedure makes a call to the procedure LowLevelPB
passing four parameters: the parameter block address, the asynch flag, the value of the
A-Trap that ends up calling the actual File Manager procedure, and a routine selector
for those procedures that are implemented with the same A-Trap (which are new, HFS
only calls). The LowLevelPB procedure immediately makes a call to an assembly
routine that calls the toolbox. The assembly routine (source in
PBFileManagerASM.ASM) must unstack the A-Trap value and the asynch flag. If the call
is to be performed asynchronously, the asynch bit in the trap word is set. In either
case, the A-Trap is installed and executed and the returned value is returned back to the
Modula-2 calling procedure (and returned back up the many levels of procedure calls!).
This has to be the simplest library module ever written, yet one of the most powerful
because it gives the Modula-2 programmer almost complete control of the Mac's file
system. That is why I thought it is an appropriate subject for this month's article.
Fig. 1 Standard file Dialog to select file name
An example program
Any module is incomplete without an example program. The program here,
MakePath.MOD, shows how to find the complete pathname to a file. The program puts up
the SFGetFile and allows the user to select any file. Then the program displays a
window with the file's complete path name (up to 255 characters, anyway...). Besides
showing how to use a few of the low-level File Manager routines, it also shows how to
determine if the host Mac is running the HFS file system and whether a volume is an
HFS or MFS volume. Because of this, the program will run on any Mac, HFS or not (fat
or skinny, regular or Plus, etc.). Macintosh Technical Note #57 says that the location
03F6h contains a global flag that says whether HFS is installed or not. Therefore, the
variable HFS in MakePath.MOD is declared as:
VAR
HFS [03f6h] : INTEGER;
If HFS = -1, the Macintosh is running MFS, else it's running HFS. When HFS is
installed, it's also necessary to determine whether a volume is a MFS or HFS volume.
The PBHGetVInfo call will return a field in the parameter block called IOVSigWord.
This variable will be D2D7h for a MFS volume and 4244h for an HFS volume.
For HFS volumes, the PBGetCatInfo call is the basis for building path names. By
passing -1 in the ioFDirIndex field, PBGetCatInfo will return information about the
directory with the WDRefNum passed in the ioVRefNum field. Every directory on an
HFS volume has a different directory ID. The root directory always has directory ID of
2. Not only does PBGetCatInfo return the directory ID (in ioDrDirID) and the
directory's name (in ioNamePtr), it also returns the directory's parent ID. By calling
PBGetCatInfo until the directory ID equals two, the path name can be built.
Fig. 2 Path Name Program constructs Path
Here are the steps for building the PBFileManager module and the example
program:
--- To make the library module... ---
1-Assemble PBFileManagerASM.ASM
2-Link (using MDS or Consulair Link) the PBFileManagerASM.REL file using the
file PBFileManagerASM.link
3-Run RMaker on PBFileManager.r
4-Rename PBFileManager.REL.RSRC to PBFileManager.REL
5-Using M2 Compiler, compile PBFileManager.DEF and PBFileManager.MOD
--- To make the example program... ---
1-Run RMaker on MakePath.r
2-Rename MakePath.REL.RSRC to MakePath.REL
3-Using M2 Compiler, compile and link MakePath.MOD
4-Execute MakePath.LOD and have fun!
----------- PBFileManager.DEF -----------
(* Tom Taylor
3707 Poinciana Dr. #137
Santa Clara, CA 95051 *)
DEFINITION MODULE PBFileManager;
(* This module defines the low level
file system described in the latest
File Manager documentation. The
types and procedures defined in
this module support both MFS and
HFS calls. *)
FROM OSQueues IMPORT
QElemPtr;
FROM MacSystemTypes IMPORT
LongCard, Ptr, OsErr,
StringPtr;
FROM FileManager IMPORT
FInfo;
FROM SYSTEM IMPORT
ADDRESS;
EXPORT QUALIFIED

(* Types *)
ParamBlkType, ParmBlkPtr, ParamBlockRec,
CMovePBPtr, CMovePBRec, HParmBlkPtr,
HParamBlockRec, WDPBPtr, WDPBRec,
CInfoType, CInfoPBPtr, CInfoPBRec,
FCBPBPtr, FCBPBRec,

(* Procedures *)
PBMountVol, PBGetVInfo, PBHGetVInfo,
PBHSetVInfo, PBGetVol, PBHGetVol,
PBSetVol, PBHSetVol, PBFlushVol,
PBUnmountVol, PBOffLine, PBEject,
PBOpen, PBHOpen, PBOpenRF,
PBHOpenRF, PBLockRange,
PBUnlockRange, PBRead, PBWrite,
PBGetFPos, PBSetFPos, PBGetEOF,
PBSetEOF, PBAllocate, PBAllocContig,
PBFlushFile, PBClose, PBCreate,
PBHCreate, PBDirCreate, PBDelete,
PBHDelete, PBGetFInfo, PBHGetFInfo,